@file:Suppress("unused")

package com.rzico.sbl.other

import android.graphics.Rect
import android.view.View
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.StaggeredGridLayoutManager
import com.xinnuo.common.helper.dp2px

class MultiGapDecoration
@JvmOverloads
constructor(
    size: Int = 10,
    private val isTopEnable: Boolean = false,
    private val isEdgeEnable: Boolean = true,
) : RecyclerView.ItemDecoration() {

    private var gapSize = dp2px(size.toFloat())

    /**
     * @param outRect 全为0的rect，用来指定偏移区域
     * @param view    指RecyclerView中的Item
     * @param parent  指RecyclerView本身
     * @param state   状态
     */
    override fun getItemOffsets(
        outRect: Rect,
        view: View,
        parent: RecyclerView,
        state: RecyclerView.State
    ) {
        super.getItemOffsets(outRect, view, parent, state)
        val position = parent.getChildLayoutPosition(view)
        val adapterPostion = parent.getChildAdapterPosition(view)

        when (parent.layoutManager) {
            is GridLayoutManager -> {
                val manager = parent.layoutManager as GridLayoutManager
                val spanCount = manager.spanCount                     //列数
                val sizeLookup = manager.spanSizeLookup               //item所占列数管理类
                val spanSize = sizeLookup.getSpanSize(adapterPostion) //当前item所占列数

                if (spanCount > 0) {
                    if (spanSize == spanCount) {
                        // item占满一行，不做偏移处理
                        outRect.set(0, 0, 0, 0)
                    } else {
                        val left: Int
                        val top: Int
                        val right: Int
                        val bottom = gapSize
                        val lastFullSpanCountPos =
                            getBeforeFullSpanCountPostion(sizeLookup, spanCount, adapterPostion)

                        // 检查是否位于网格中的最后一列
                        val isLastCol = isLastGridCol(spanCount, position, lastFullSpanCountPos)

                        when (spanCount) {
                            2 -> {
                                // 这里这样分割主要为了让每个grid当中的item的宽度都是保持一致
                                right = if (isLastCol) gapSize else gapSize / 2
                                left = if (isLastCol) gapSize / 2 else gapSize
                            }
                            3 -> {
                                when ((position - lastFullSpanCountPos) % (spanCount / spanSize)) {
                                    0 -> { //一行最后一个
                                        right = if (isEdgeEnable) gapSize else 0
                                        left = if (isEdgeEnable) gapSize / 2 else gapSize * 7 / 10
                                    }
                                    1 -> { //一行第一个
                                        right = if (isEdgeEnable) gapSize / 2 else gapSize * 7 / 10
                                        left = if (isEdgeEnable) gapSize else 0
                                    }
                                    else -> {
                                        right = if (isEdgeEnable) gapSize / 2 else gapSize * 3 / 10
                                        left = if (isEdgeEnable) gapSize / 2 else gapSize * 3 / 10
                                    }
                                }
                            }
                            else -> {
                                when ((position - lastFullSpanCountPos) % (spanCount / spanSize)) {
                                    0 -> { //一行最后一个
                                        right = if (isEdgeEnable) gapSize else 0
                                        left = gapSize / 2
                                    }
                                    1 -> { //一行第一个
                                        right = gapSize / 2
                                        left = if (isEdgeEnable) gapSize else 0
                                    }
                                    else -> {
                                        right = gapSize / 2
                                        left = gapSize / 2
                                    }
                                }
                            }
                        }

                        // 检查是否允许网格中的第一行元素的marginTop是否允许设置值 -true标识允许
                        top = if (isTopEnable && isFristGridRow(
                                spanCount,
                                position,
                                lastFullSpanCountPos
                            )
                        ) gapSize else 0

                        outRect.set(left, top, right, bottom)
                    }
                }
            }
            is LinearLayoutManager -> {
                outRect.set(0, 0, 0, 0)
                return
            }
            is StaggeredGridLayoutManager -> throw IllegalAccessError("暂时不支持瀑布流")
        }
    }

    /**
     * 寻找上方最近一个占据spanCount整列的位置
     */
    private fun getBeforeFullSpanCountPostion(
        sizeLookup: GridLayoutManager.SpanSizeLookup,
        spanCount: Int,
        adapterPostion: Int
    ): Int {
        (adapterPostion downTo 0).forEach {
            if (sizeLookup.getSpanSize(it) == spanCount) return it
        }
        return -1
    }

    /**
     * 寻找下方最近一个占据spanCount整列的位置
     */
    private fun getLastFullSpanCountPostion(
        sizeLookup: GridLayoutManager.SpanSizeLookup,
        spanCount: Int,
        itemCount: Int,
        adapterPostion: Int
    ): Int {
        (adapterPostion until itemCount).forEach {
            if (sizeLookup.getSpanSize(it) == spanCount) return it
        }
        return -1
    }

    /**
     * 是否为最后一列数据
     */
    private fun isLastGridCol(
        spanCount: Int,
        position: Int,
        lastFullSpanPosition: Int
    ) = (position - lastFullSpanPosition) % spanCount == 0

    /**
     * 是否为第一行数据到上方最近一个占据spanCount整列
     */
    private fun isFristGridRow(
        spanCount: Int,
        position: Int,
        lastFullSpanPosition: Int
    ) = position - lastFullSpanPosition <= spanCount

    /**
     * 是否为全部数据的最后一行
     */
    private fun isLastGridRow(
        spanCount: Int,
        position: Int,
        itemCount: Int
    ) = itemCount - position <= spanCount

}
